<!doctype html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
<script>
    /*
    * 组合模式：
    *   组合模式将对象合成树形结构，以表示"部分与整体"的结构层次。除了用来表示树形结构之外，
    *   组合模式的另一个好处是通过对象的多态性表现，使得用户对单个对象和组合对象的使用具有一致性。
    *
    * */
    let Combine = function (){
        return { //返回一个对象
            lists:[], //创建一个数组来保存接收到的任务，每次执行Combine函数就会创建一个列表数组来保存数据任务
            add:function (task){ //该方法可以接收一个任务
                this.lists.push(task) //将接收的任务添加到任务数组lists中
            },
            excute:function (){ //该方法可以调用添加到任务数组中的所有方法
                for(i of this.lists){ //for of循环遍历任务数组中的所有对象
                    i.excute()
                }
            },
        }
    }

    //先生成三个子节点
    //子节点1
    let command1 = Combine() //创建第1个对象
    command1.add({ //对象调用add方法，将对象{excute:fn()}添加到command1的任务列表中
        excute:function (){
            console.log("1")
        },
    })
    console.log(command1)

    //子节点2
    let command2 = Combine() //创建第2个对象
    command2.add({
        excute:function (){
            console.log("2")
        },
    })
    command2.add({
        excute:function (){
            console.log("3")
        },
    })

    //子节点3
    let command3 = Combine() //创建第3个对象
    command3.add({
        excute:function (){
            console.log("4")
        },
    })
    command3.add({
        excute:function (){
            console.log("5")
        },
    })

    //再给这三个子节点添加一个父节点
    let command = Combine()
    //再将这三个子节点添加到父节点内
    command.add(command1)
    command.add(command2)
    command.add(command3)

    command.excute() //command对象调用excute方法



</script>
</body>
</html>